import { scriptModel, versionModel, folderModel, type IScript, type IVersion } from '../database/models';

export interface CreateScriptData {
  name: string;
  content?: string;
  description?: string;
  tags?: string[];
  folder_id?: string;
  created_by?: string;
}

export interface UpdateScriptData {
  name?: string;
  content?: string;
  description?: string;
  tags?: string[];
  folder_id?: string;
}

export interface SearchScriptOptions {
  keyword?: string;
  tags?: string[];
  folder_id?: string;
  created_by?: string;
  limit?: number;
  offset?: number;
}

export class ScriptService {
  // 创建脚本
  async createScript(data: CreateScriptData): Promise<IScript> {
    // 验证文件夹是否存在
    if (data.folder_id) {
      const folder = await folderModel.findById(data.folder_id);
      if (!folder) {
        throw new Error('指定的文件夹不存在');
      }
    }
    
    // 检查脚本名称在同一文件夹下是否唯一
    const isUnique = await scriptModel.isNameUniqueInFolder(data.name, data.folder_id);
    if (!isUnique) {
      throw new Error('同一文件夹下已存在相同名称的脚本');
    }
    
    // 创建脚本
    const script = await scriptModel.create({
      name: data.name,
      content: data.content || '',
      description: data.description,
      tags: data.tags || [],
      folder_id: data.folder_id,
      created_by: data.created_by
    });
    
    // 如果有内容，创建初始版本
    if (data.content && data.content.trim()) {
      await versionModel.createVersion({
        script_id: script.id,
        content: data.content,
        message: '初始版本',
        author: data.created_by
      });
    }
    
    return script;
  }
  
  // 更新脚本
  async updateScript(id: string, data: UpdateScriptData, author?: string): Promise<IScript> {
    const existingScript = await scriptModel.findById(id);
    if (!existingScript) {
      throw new Error('脚本不存在');
    }
    
    // 如果更新名称，检查唯一性
    if (data.name && data.name !== existingScript.name) {
      const isUnique = await scriptModel.isNameUniqueInFolder(
        data.name, 
        data.folder_id || existingScript.folder_id, 
        id
      );
      if (!isUnique) {
        throw new Error('同一文件夹下已存在相同名称的脚本');
      }
    }
    
    // 如果更新文件夹，验证文件夹是否存在
    if (data.folder_id && data.folder_id !== existingScript.folder_id) {
      const folder = await folderModel.findById(data.folder_id);
      if (!folder) {
        throw new Error('指定的文件夹不存在');
      }
    }
    
    // 更新脚本
    const updateData: any = {};
    if (data.name !== undefined) updateData.name = data.name;
    if (data.description !== undefined) updateData.description = data.description;
    if (data.tags !== undefined) updateData.tags = data.tags;
    if (data.folder_id !== undefined) updateData.folder_id = data.folder_id;
    
    // 如果内容发生变化，创建新版本
    if (data.content !== undefined && data.content !== existingScript.content) {
      updateData.content = data.content;
      
      // 创建新版本
      await versionModel.createVersion({
        script_id: id,
        content: data.content,
        message: '内容更新',
        author: author
      });
    }
    
    const updatedScript = await scriptModel.update(id, updateData);
    return updatedScript;
  }
  
  // 删除脚本
  async deleteScript(id: string): Promise<boolean> {
    const script = await scriptModel.findById(id);
    if (!script) {
      throw new Error('脚本不存在');
    }
    
    // 删除所有版本
    await versionModel.deleteVersionsByScriptId(id);
    
    // 删除脚本
    return await scriptModel.delete(id);
  }
  
  // 获取脚本详情
  async getScript(id: string): Promise<IScript | null> {
    return await scriptModel.getScriptWithPath(id);
  }
  
  // 搜索脚本
  async searchScripts(options: SearchScriptOptions): Promise<{
    scripts: IScript[];
    total: number;
    page: number;
    pageSize: number;
    totalPages: number;
  }> {
    const limit = options.limit || 20;
    const offset = options.offset || 0;
    const page = Math.floor(offset / limit) + 1;
    
    const result = await scriptModel.search({
      keyword: options.keyword,
      tags: options.tags,
      folderId: options.folder_id,
      createdBy: options.created_by,
      limit,
      offset
    });
    
    const totalPages = Math.ceil(result.total / limit);
    
    return {
      scripts: result.scripts,
      total: result.total,
      page,
      pageSize: limit,
      totalPages
    };
  }
  
  // 获取脚本列表（按文件夹）
  async getScriptsByFolder(folderId?: string): Promise<IScript[]> {
    if (folderId) {
      return await scriptModel.findByFolderId(folderId);
    } else {
      return await scriptModel.findAll({
        where: { folder_id: null },
        orderBy: 'name',
        orderDirection: 'ASC'
      });
    }
  }
  
  // 移动脚本到其他文件夹
  async moveScript(id: string, folderId?: string): Promise<IScript> {
    const script = await scriptModel.findById(id);
    if (!script) {
      throw new Error('脚本不存在');
    }
    
    // 验证目标文件夹
    if (folderId) {
      const folder = await folderModel.findById(folderId);
      if (!folder) {
        throw new Error('目标文件夹不存在');
      }
    }
    
    // 检查名称冲突
    const isUnique = await scriptModel.isNameUniqueInFolder(script.name, folderId, id);
    if (!isUnique) {
      throw new Error('目标文件夹下已存在相同名称的脚本');
    }
    
    await scriptModel.moveToFolder(id, folderId);
    return await scriptModel.findById(id);
  }
  
  // 复制脚本
  async copyScript(id: string, options: { name?: string; folder_id?: string; created_by?: string } = {}): Promise<IScript> {
    const originalScript = await scriptModel.findById(id);
    if (!originalScript) {
      throw new Error('原脚本不存在');
    }
    
    const newName = options.name || `${originalScript.name}_副本_${Date.now()}`;
    
    // 检查新名称是否唯一
    const isUnique = await scriptModel.isNameUniqueInFolder(newName, options.folder_id);
    if (!isUnique) {
      throw new Error('目标文件夹下已存在相同名称的脚本');
    }
    
    // 创建副本
    const copyData: CreateScriptData = {
      name: newName,
      content: originalScript.content,
      description: originalScript.description ? `${originalScript.description} (副本)` : '副本',
      tags: originalScript.tags || [],
      folder_id: options.folder_id,
      created_by: options.created_by
    };
    
    return await this.createScript(copyData);
  }
  
  // 批量更新脚本标签
  async updateScriptTags(id: string, tags: string[]): Promise<boolean> {
    const script = await scriptModel.findById(id);
    if (!script) {
      throw new Error('脚本不存在');
    }
    
    return await scriptModel.updateTags(id, tags);
  }
  
  // 获取用户脚本统计
  async getUserScriptStats(userId: string): Promise<{
    total: number;
    byFolder: Array<{ folder_name: string; count: number }>;
    byTag: Array<{ tag: string; count: number }>;
  }> {
    return await scriptModel.getUserScriptStats(userId);
  }
  
  // 获取脚本的版本历史
  async getScriptVersions(scriptId: string, options: {
    limit?: number;
    offset?: number;
  } = {}): Promise<IVersion[]> {
    const script = await scriptModel.findById(scriptId);
    if (!script) {
      throw new Error('脚本不存在');
    }
    
    return await versionModel.getVersionHistory(scriptId, options);
  }
  
  // 回滚脚本到指定版本
  async revertScriptToVersion(scriptId: string, versionId: string, author?: string): Promise<IScript> {
    const script = await scriptModel.findById(scriptId);
    if (!script) {
      throw new Error('脚本不存在');
    }
    
    const version = await versionModel.findById(versionId);
    if (!version || version.script_id !== scriptId) {
      throw new Error('版本不存在或不属于该脚本');
    }
    
    // 更新脚本内容
    const updatedScript = await scriptModel.update(scriptId, {
      content: version.content
    });
    
    // 创建回滚版本记录
    await versionModel.createVersion({
      script_id: scriptId,
      content: version.content,
      message: `回滚到版本 ${version.version}`,
      author: author,
      parent_version: version.id
    });
    
    return updatedScript;
  }
  
  // 比较脚本版本
  async compareScriptVersions(versionId1: string, versionId2: string) {
    return await versionModel.compareVersions(versionId1, versionId2);
  }

  // ==================== 批量操作 ====================

  // 批量删除脚本
  async batchDeleteScripts(scriptIds: string[]): Promise<{
    success_count: number;
    failed_count: number;
    errors: string[];
  }> {
    let successCount = 0;
    let failedCount = 0;
    const errors: string[] = [];

    for (const scriptId of scriptIds) {
      try {
        await this.deleteScript(scriptId);
        successCount++;
      } catch (error: any) {
        failedCount++;
        errors.push(`脚本 ${scriptId}: ${error.message}`);
      }
    }

    return {
      success_count: successCount,
      failed_count: failedCount,
      errors
    };
  }

  // 批量移动脚本
  async batchMoveScripts(scriptIds: string[], folderId?: string): Promise<{
    success_count: number;
    failed_count: number;
    errors: string[];
  }> {
    let successCount = 0;
    let failedCount = 0;
    const errors: string[] = [];

    for (const scriptId of scriptIds) {
      try {
        await this.moveScript(scriptId, folderId);
        successCount++;
      } catch (error: any) {
        failedCount++;
        errors.push(`脚本 ${scriptId}: ${error.message}`);
      }
    }

    return {
      success_count: successCount,
      failed_count: failedCount,
      errors
    };
  }

  // 批量更新标签
  async batchUpdateTags(scriptIds: string[], tags: string[]): Promise<{
    success_count: number;
    failed_count: number;
    errors: string[];
  }> {
    let successCount = 0;
    let failedCount = 0;
    const errors: string[] = [];

    for (const scriptId of scriptIds) {
      try {
        await this.updateScriptTags(scriptId, tags);
        successCount++;
      } catch (error: any) {
        failedCount++;
        errors.push(`脚本 ${scriptId}: ${error.message}`);
      }
    }

    return {
      success_count: successCount,
      failed_count: failedCount,
      errors
    };
  }

  // ==================== 导入导出 ====================

  // 导入脚本
  async importScripts(files: Express.Multer.File[], options: {
    folder_id?: string;
    created_by?: string;
  } = {}): Promise<{
    success_count: number;
    failed_count: number;
    imported_scripts: IScript[];
    errors: string[];
  }> {
    let successCount = 0;
    let failedCount = 0;
    const importedScripts: IScript[] = [];
    const errors: string[] = [];

    for (const file of files) {
      try {
        const content = file.buffer.toString('utf-8');
        const name = file.originalname.replace(/\.[^/.]+$/, ''); // 移除文件扩展名
        
        // 检查名称唯一性，如果重复则添加时间戳
        let finalName = name;
        let counter = 1;
        while (!(await scriptModel.isNameUniqueInFolder(finalName, options.folder_id))) {
          finalName = `${name}_${counter}`;
          counter++;
        }

        const scriptData: CreateScriptData = {
          name: finalName,
          content,
          description: `从文件 ${file.originalname} 导入`,
          tags: ['导入'],
          folder_id: options.folder_id,
          created_by: options.created_by
        };

        const script = await this.createScript(scriptData);
        importedScripts.push(script);
        successCount++;
      } catch (error: any) {
        failedCount++;
        errors.push(`文件 ${file.originalname}: ${error.message}`);
      }
    }

    return {
      success_count: successCount,
      failed_count: failedCount,
      imported_scripts: importedScripts,
      errors
    };
  }

  // 导出脚本
  async exportScripts(scriptIds: string[], format: string = 'zip'): Promise<{
    buffer: Buffer;
    filename: string;
  }> {
    const scripts = [];
    
    for (const scriptId of scriptIds) {
      const script = await scriptModel.findById(scriptId);
      if (script) {
        scripts.push(script);
      }
    }

    if (scripts.length === 0) {
      throw new Error('没有找到要导出的脚本');
    }

    if (format === 'zip') {
      const JSZip = require('jszip');
      const zip = new JSZip();

      for (const script of scripts) {
        const filename = `${script.name}.sql`;
        const content = script.content || '';
        zip.file(filename, content);
      }

      const buffer = await zip.generateAsync({ type: 'nodebuffer' });
      return {
        buffer,
        filename: `scripts_export_${Date.now()}.zip`
      };
    } else {
      throw new Error('不支持的导出格式');
    }
  }

  // ==================== 标签管理 ====================

  // 获取所有标签
  async getAllTags(): Promise<Array<{ tag: string; count: number }>> {
    return await scriptModel.getAllTags();
  }

}